use base64::engine::general_purpose::STANDARD;
use base64::prelude::*;
use lofty::config::WriteOptions;
use lofty::picture::Picture;
use lofty::prelude::*;
use lofty::probe::Probe;
use lofty::tag::Tag;
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct AudioInfo {
    pub path: String,         // 路径
    pub title: String,        // 标题
    pub artist: String,       // 艺术家
    pub album: String,        // 专辑
    pub genre: String,        // 流派
    pub album_artist: String, // 专辑艺术家
    pub duration: u64,        // 时长
    pub bitrate: u32,         // 比特率
    pub sample_rate: u32,     // 采样率
    pub bit_depth: u8,        // 比特深度
    pub channels: u8,         // 声道数
    pub year: u32,            // 年份
    pub track: u32,           // 轨道
    pub comment: String,      // 注释
    pub size: u64,            // 文件大小
    pub lyric: String,        // 歌词
    // pub cover: Vec<u8>, // 封面
    pub cover: String, // 封面 base64 编码
    pub dir: String,   // 文件夹名字
}

// 检测音频文件的基本信息
pub fn detect_audio_info(path_str: &str) -> Option<AudioInfo> {
    let path = Path::new(&path_str);

    if !path.is_file() {
        return None;
    }

    let tagged_file = match Probe::open(path) {
        Ok(file) => match file.read() {
            Ok(tagged_file) => tagged_file,
            Err(_) => {
                return None;
            }
        },
        Err(_) => {
            return None;
        }
    };

    let tag = match tagged_file.primary_tag() {
        Some(primary_tag) => primary_tag,
        None => match tagged_file.first_tag() {
            Some(first_tag) => first_tag,
            None => return None,
        },
    };
    let properties = tagged_file.properties();

    let audio_info = AudioInfo {
        path: path_str.to_string(),
        dir: path
            .parent()
            .unwrap()
            .file_name()
            .unwrap()
            .to_string_lossy()
            .to_string(),
        title: tag.title().as_deref().unwrap_or("").to_string(),
        artist: tag.artist().as_deref().unwrap_or("").to_string(),
        album: tag.album().as_deref().unwrap_or("").to_string(),
        genre: tag.genre().as_deref().unwrap_or("").to_string(),
        album_artist: tag
            .get_string(&ItemKey::AlbumArtist)
            .unwrap_or("")
            .to_string(),
        duration: properties.duration().as_secs(),
        bitrate: properties.audio_bitrate().unwrap_or(0),
        sample_rate: properties.sample_rate().unwrap_or(0),
        channels: properties.channels().unwrap_or(0),
        bit_depth: properties.bit_depth().unwrap_or(0),
        year: tag.year().unwrap_or(0),
        track: tag.track().unwrap_or(0),
        comment: tag.comment().as_deref().unwrap_or("").to_string(),
        size: path.metadata().unwrap().len(),
        lyric: tag.get_string(&ItemKey::Lyrics).unwrap_or("").to_string(),
        // cover: tag.pictures().first().map(|picture| picture.data().to_vec()).unwrap_or(vec![]),
        cover: convert_u8_to_base64(tag.pictures().first()),
    };

    return Some(audio_info);
}

// 将u8类型的图片转换为base64类型的字符串
fn convert_u8_to_base64(input: Option<&Picture>) -> String {
    return match input {
        Some(pic) => {
            let ty = pic.mime_type().unwrap().to_string();
            let img = STANDARD.encode(pic.data());
            std::format!("data:{};base64,{}", ty, img)
            // println!("src len: {}, base64 len {}", pic.data().len(), img.len());
            // return ty;
        }
        None => "".to_string(),
    };
}

fn check_audio_lyric(path: &Path) -> String {
    let ext = path.extension().unwrap();
    let path_str = path.as_os_str().to_string_lossy().to_string();
    let mut lyric = path_str
        .strip_suffix(ext.to_str().unwrap())
        .unwrap()
        .to_string();
    lyric += "lrc";
    let lyric_path = Path::new(&lyric);
    if lyric_path.is_file() {
        return fs::read_to_string(lyric_path).unwrap_or_default();
    }
    return "".to_string();
}

// 扫描文件夹下的音频文件，返回音频文件的详细信息
// 可以控制是否扫描子文件夹
pub fn scan_audio_info(path_str: &str, recursion: bool) -> Option<Vec<AudioInfo>> {
    let path = Path::new(&path_str);
    if !path.is_dir() {
        return None;
    }

    let mut audio_infos = Vec::new();

    for entry in path.read_dir().unwrap() {
        let entry_sub = entry.unwrap();
        let path_sub = entry_sub.path();
        if path_sub.is_file() {
            let audio_info = detect_audio_info(path_sub.to_str().unwrap());
            if let Some(mut audio_info2) = audio_info {
                // 如果没有歌词，尝试读取对应的歌词文件
                if audio_info2.lyric.is_empty() {
                    audio_info2.lyric = check_audio_lyric(path_sub.as_path());
                }
                // println!("{:?}", audio_info2);
                audio_infos.push(audio_info2);
            }
        }
        if path_sub.is_dir() && recursion {
            let sub_infs = scan_audio_info(path_sub.to_str().unwrap(), recursion);
            if let Some(sub_infs2) = sub_infs {
                audio_infos.extend(sub_infs2);
            }
        }
    }

    return Some(audio_infos);
}

// 修改音乐文件的tag信息
pub fn modify_audio_tag(path_str: &str, inf: AudioInfo) -> bool {
    let path = Path::new(&path_str);

    if !path.is_file() {
        return false;
    }

    let mut tagged_file = match Probe::open(path) {
        Ok(file) => match file.read() {
            Ok(tagged_file) => tagged_file,
            Err(_) => {
                return false;
            }
        },
        Err(_) => {
            return false;
        }
    };
    let tag = &mut match tagged_file.primary_tag_mut() {
        Some(primary_tag) => primary_tag,
        None => match tagged_file.first_tag_mut() {
            Some(first_tag) => first_tag,
            None => {
                if let Some(first_tag) = tagged_file.first_tag_mut() {
                    first_tag
                } else {
                    let tag_type = tagged_file.primary_tag_type();

                    eprintln!("WARN: No tags found, creating a new tag of type `{tag_type:?}`");
                    tagged_file.insert_tag(Tag::new(tag_type));

                    tagged_file.primary_tag_mut().unwrap()
                }
            }
        },
    };

    if !inf.album.is_empty() {
        tag.set_album(inf.album);
    }
    if !inf.artist.is_empty() {
        tag.set_artist(inf.artist);
    }
    if !inf.album_artist.is_empty() {
        tag.insert_text(ItemKey::AlbumArtist, inf.album_artist);
    }
    if !inf.comment.is_empty() {
        tag.set_comment(inf.comment);
    }
    if !inf.genre.is_empty() {
        tag.set_genre(inf.genre);
    }
    if !inf.title.is_empty() {
        tag.set_title(inf.title);
    }
    // if inf.duration > 0 {
    //     tag.set_duration(inf.duration);
    // }
    // if inf.bitrate > 0 {
    //     tag.set_audio_bitrate(inf.bitrate);
    // }
    // if inf.sample_rate > 0 {
    //     tag.set_sample_rate(inf.sample_rate);
    // }
    // if inf.channels > 0 {
    //     tag.set_channels(inf.channels);
    // }
    if inf.year > 0 {
        tag.set_year(inf.year);
    }
    if inf.track > 0 {
        tag.set_track(inf.track);
    }
    if !inf.lyric.is_empty() {
        tag.insert_text(ItemKey::Lyrics, inf.lyric);
    }
    // if!inf.cover.is_empty() {
    //     let cover = convert_base64_to_u8(inf.cover);
    //     if cover.is_some() {
    //         tag.insert_picture(Picture::new(cover.unwrap(), inf.cover));
    //     }
    // }
    tag.save_to_path(path, WriteOptions::default()).unwrap();
    return true;
}
